import React, { useEffect, useState } from 'react';
import { connect, Dispatch } from 'umi';
import { ConnectState, IResponse } from '@/models/connect';
import styles from './index.less';
import { ICurrentUser } from '@/models/user';
import {
  EditOutlined,
  ExclamationCircleOutlined,
  FilterOutlined,
  FolderFilled,
  FundFilled,
  FundProjectionScreenOutlined,
  GroupOutlined,
  LeftOutlined,
  PlusOutlined,
} from '@ant-design/icons';
import { getToken } from '@/utils/token';
import PCWidgetLayout from './PCWidgetLayout';
import { dashboardGroupsItem, dashboardWidgetsItem, IDashboardItem, IWidget } from '@/pages/SelfQuery/type';
import { Dropdown, Input, Menu, message, Modal, TreeSelect } from 'antd';
import GroupRenameModel from '@/pages/Analysis/Board/BoardDesign/GroupRenameModel';
import GroupWidgetAddModel from '@/pages/Analysis/Board/BoardDesign/GroupWidgetAddModel';
import GroupAddModel from './GroupAddModel';
import GlobalControlConfig from '@/pages/Analysis/Board/components/Filters/config/FilterConfig';
import { GlobalControlQueryMode, IGlobalControl } from '@/pages/Analysis/Board/components/Filters/types';
import FilterForm from '@/pages/Analysis/Board/BoardDesign/FilterForm';
import { getDashboardWidgetFilters } from '@/pages/Analysis/utils';
import { addWidgets, getWidgetByProjectId, renameDashboard, updateFilterConfig } from '@/services/analysis';
import { ISheetItem } from '@/pages/Analysis/type';
import ViewSelect from '@/pages/Analysis/Board/BoardDesign/ViewSelect';
import { IDashboard, ITreeNode } from '@/pages/data';

const { confirm } = Modal;
const classnames = require('classnames');


interface PanelProps {
  dispatch: Dispatch;
  currentUser: ICurrentUser
  onCanel?: () => void
  //看板
  board: IDashboardItem
  initBoard: () => void
  projectId: number
  sheetList: ISheetItem[]
}

const { davinciUrl } = process.env;
const BoardDesign: React.FC<PanelProps> = (props) => {
  let { onCanel, board, currentUser, dispatch, initBoard, projectId, sheetList } = props;
  const [titleEditIng, setTitleEditIng] = useState<boolean>(false);
  const [currentGroupId, setCurrentGroupId] = useState<number>(0);
  const [currentGroupWidgetIds, setCurrentGroupWidgetIds] = useState<number[]>([]);
  const [groups, setGroups] = useState<dashboardGroupsItem[]>([]);
  const [renameModalVisible, setRenameModalVisible] = useState<boolean>(false); // 重命名弹框
  const [indexModalVisible, setIndexModalVisible] = useState<boolean>(false); // 添加指标弹框
  const [groupAddModalVisible, setGroupAddModalVisible] = useState<boolean>(false); // 添加创建分组弹框
  const [widgetAddModalVisible, setWidgetAddModalVisible] = useState<boolean>(false); // 添加新增指标弹框
  const [globalControlConfigModalVisible, setGlobalControlConfigModalVisible] = useState<boolean>(false); // 全局筛选弹框
  const [menuHover, setMenuHover] = useState<boolean>(false); // 鼠标悬停
  const [notInGroupWidgets, setNotInGroupWidgets] = useState<dashboardWidgetsItem[]>([]); // 添加指标弹框
  const [filterValues, setFilterValues] = useState<any>({});
  const [controls, setControls] = useState<IGlobalControl[]>([]);
  const [viewSelectVisible, setViewSelectVisible] = useState<boolean>(false);
  const [widgetTrees, setWidgetTrees] = useState<any[]>([]);
  const [expandedKeys, setExpandedKeys] = useState<Array<string>>([]); // 展开指定的树节点
  const [dashboardName, setDashboardName] = useState<string>(); // 展开指定的树节点
  const [dashboardWidgets, setBashboardWidgets] = useState<{ dashboards: IDashboard[], widgets: IWidget[] }>({
    dashboards: [],
    widgets: [],
  });
  useEffect(() => {
    if (board) {
      setDashboardName(board.name);
      if (board.config) {
        const filters = JSON.parse(board.config);
        let filterList = [];
        if (filters && filters.filters) {
          filterList = filters.filters;
        }
        setControls(filterList);
      }
    }
    dispatch({
      type: 'sheet/fetchSheetListByProjectId',
      payload: projectId,
      callback: (res: ISheetItem[]) => {
      },
    });
    getWidgetByProjectId({ projectId }).then((res: IResponse) => {
      if (res.header.code === 200) {
        setBashboardWidgets(res.payload);
      }
    });

  }, [board]);

  useEffect(() => {
    if (dashboardWidgets.widgets.length) {
      const { dashboards, widgets } = dashboardWidgets;
      // 初始化文件夹树形结构

      const dashboardFolders: ITreeNode[] = dashboards.sort((a: any, b: any) => a.type - b.type).map(d => ({
        key: d.id,
        value: d.id,
        title: d.name,
        parent: d.parentId,
        isFolder: true,
        icon: d.type === 0 ?
          <FolderFilled style={{ color: '#FFC53D', marginRight: '12px' }} />
          : <FundFilled style={{ color: '#40A9FF', marginRight: '12px' }} />,
      }));
      const widgetFolders: ITreeNode[] = widgets.map(d => ({
        key: `${d.dashboard.id}-${d.id}`,
        value: `${d.dashboard.id}-${d.id}`,
        title: d.name,
        isLeaf: true,
        parent: d.dashboard.id,
        isFolder: false,
      }));
      const folders = [...dashboardFolders, ...widgetFolders];
      const searchFoldersById = (datas: ITreeNode[], pId: any) => {
        const children = datas.filter(v => v.parent === pId);
        if (children) {
          children.map(v => {
            const children1 = searchFoldersById(datas, v.key);
            v.children = children1;
            return v;
          });
        }
        return children;
      };
      const folderTrees = folders.filter((tree: any) => !tree.parent || tree.parent === '' || tree.parent === 0).map((root) => {
        root.children = searchFoldersById(folders, root.key);
        return root;
      });
      setWidgetTrees(folderTrees);
    }

  }, [dashboardWidgets]);
  useEffect(() => {
    if (board && board.groups && board.groups.length) {
      let groupItems: dashboardGroupsItem[] = [...board.groups];
      const { widgets } = board;
      let allWidgetIds: number[] = [];
      board.groups.forEach(g => {
        allWidgetIds = [...allWidgetIds, ...g.widgets.split(',').map(v => Number(v))];
      });
      const notInGroupWidgetList = widgets.filter(w => !allWidgetIds.includes(w.widgetId));
      setNotInGroupWidgets(notInGroupWidgetList);
      const notInGroupWidgetIds = notInGroupWidgetList.map(w => w.widgetId);
      if (notInGroupWidgetIds && notInGroupWidgetIds.length) {
        groupItems = [...groupItems, { id: -1, groupName: '未分组', widgets: notInGroupWidgetIds.join(',') }];
      }
      setGroups(groupItems);
      const groupIds = groupItems.map(g => g.id);
      let groupId = groupIds[0];
      //非初始化复制
      if (currentGroupId !== 0 && groupIds.includes(currentGroupId)) {
        groupId = currentGroupId;
      }
      setCurrentGroupId(groupId);
      const group = board.groups.find(g => g.id === groupId);
      if (group) {
        setCurrentGroupWidgetIds(group.widgets.split(',').map(d => Number(d)));
      }
    } else {
      // @ts-ignore
      setCurrentGroupWidgetIds(undefined);
      setNotInGroupWidgets(board.widgets);
      setGroups([]);
    }
  }, [board]);
  const addWidget = (viewId: number) => {
    const widgetUrl = `${davinciUrl}/#/project/${projectId}/widget?token=${getToken()}
    &loginUser=${currentUser}&boardId=${board.id}&viewId=${viewId}`;
    window.location.href = widgetUrl;
  };
  // 重命名
  const rename = () => {
    setRenameModalVisible(true);
  };

  // 添加指标
  const add = () => {
    setIndexModalVisible(true);
  };

  // 删除分组
  const remove = () => {
    confirm({
      title: '确认要删除分组吗?',
      icon: <ExclamationCircleOutlined />,
      okText: '确定',
      cancelText: '取消',
      onOk() {
        dispatch({
          type: 'board/deletGroup',
          payload: {
            id: currentGroupId,
          },
          callback: (res: IResponse) => {
            const { header } = res;
            if (header.code === 200) {
              message.success('删除成功');
              initBoard();
            } else {
              message.warning('删除失败');
            }
          },
        });
      },
    });
  };
  // 分组删除指标
  const groupRemoveWidget = (id: number) => {
    confirm({
      title: '确认要移除指标吗？',
      icon: <ExclamationCircleOutlined />,
      okText: '确定',
      cancelText: '取消',
      onOk() {
        const widgetsID = currentGroupWidgetIds.filter(v => v !== id);
        dispatch({
          type: 'board/updateGroup',
          payload: { id: currentGroupId, widgets: widgetsID },
          callback: (res: IResponse) => {
            const { header } = res;
            if (header.code === 200) {
              message.success('移除指标成功');
              initBoard();
            } else {
              message.warning('移除指标失败');
            }
          },
        });
      },
    });
  };

  // 看板删除指标
  const removeWidgets = (id: number) => {
    confirm({
      title: '确认要移除指标吗？',
      icon: <ExclamationCircleOutlined />,
      okText: '确定',
      cancelText: '取消',
      onOk() {
        dispatch({
          type: 'board/deleteWidgets',
          payload: { relationId: id },
          callback: (res: IResponse) => {
            const { header } = res;
            if (header.code === 200) {
              message.success('移除指标成功');
              initBoard();
            } else {
              message.warning('移除指标失败');
            }
          },
        });
      },
    });
  };
  const tabMenu = (
    <Menu>
      <Menu.Item>
        <GroupWidgetAddModel
          visible={indexModalVisible}
          widgets={notInGroupWidgets}
          onCancel={() => {
            setIndexModalVisible(false);
          }}
          onSure={(values: string[]) => {
            dispatch({
              type: 'board/updateGroup',
              payload: { id: currentGroupId, widgets: [...currentGroupWidgetIds, ...values.map(v => Number(v))] },
              callback: (res: IResponse) => {
                const { header } = res;
                if (header.code === 200) {
                  message.success('添加指标成功');
                  initBoard();
                  setIndexModalVisible(false);
                } else {
                  message.warning('添加指标失败');
                }
              },
            });
          }
          }
        />
        <div onClick={() => {
          add();
        }}>添加指标
        </div>
      </Menu.Item>
      <Menu.Item>
        <GroupRenameModel
          visible={renameModalVisible}
          onCancel={() => setRenameModalVisible(false)}
          onCallBack={(res: IResponse, name: string) => {
            const { header } = res;
            if (header.code === 200) {
              message.success('重命名成功');
              setGroups(groups.map(g => {
                if (g.id === currentGroupId) {
                  return { ...g, groupName: name };
                }
                return g;
              }));
              setRenameModalVisible(!renameModalVisible);
            } else {
              message.warning('重命名失败');
            }
          }
          }
          groupId={currentGroupId}
        />
        <div onClick={() => {
          rename();
        }}>重命名
        </div>
      </Menu.Item>
      <Menu.Item>
        <div onClick={() => {
          remove();
        }}>删除分组
        </div>
      </Menu.Item>
    </Menu>
  );
  return (
    <div className={styles.boardDesign}>
      <div className={styles.header}>
        <div className={styles.titleContent}>
          <LeftOutlined className={styles.backIcon} onClick={onCanel} />
          <div className={styles.title}>
            {
              !titleEditIng ?
                dashboardName :
                <Input value={dashboardName} size='large' onChange={(e) => {
                  setDashboardName(e.target.value);
                }
                } />
            }
          </div>
          {
            !titleEditIng ? <EditOutlined className={styles.editTitle} onClick={() => {
                setTitleEditIng(true);
              }} />
              : <div className={styles.titleBtn}>
                <div className={styles.titleCheck} onClick={() => {
                  renameDashboard({ id: board.id, name: dashboardName }).then((res: IResponse) => {
                    if (res.header.code === 200) {
                      setTitleEditIng(false);
                    }
                  });
                }
                }>
                  <i className='fa fa-check' aria-hidden='true' />
                </div>
                <div
                  className={styles.titleClose}
                  onClick={() => {
                    setTitleEditIng(false);
                  }}
                >
                  <i className='fa fa-close' aria-hidden='true' />
                </div>
              </div>
          }

        </div>
        <div className={styles.platformTabs}>
          <div className={classnames({
            [styles.tabClicked]: true,
          })}>PC端
          </div>
          <div className={styles.h5Tab}>移动端</div>
        </div>
        <div className={styles.btns}>
          <div className={styles.deleteBtn}>删除</div>
          <div className={styles.saveBtn}>保存</div>
        </div>
      </div>
      <div className={styles.contain}>
        <div className={styles.leftTabs}>
          <GlobalControlConfig
            board={board}
            visible={globalControlConfigModalVisible}
            onCancel={() => setGlobalControlConfigModalVisible(false)}
            onSave={(filterItems: any[], queryMode: GlobalControlQueryMode) => {
              let config;
              try {
                config = JSON.parse(board.config);
              } catch (e) {
                config = {};
              }
              const newConfig = { ...config, filters: filterItems, queryMode };
              updateFilterConfig({ id: board.id, config: JSON.stringify(newConfig) }).then((res: IResponse) => {
                if (res.header.code === 200) {
                  setGlobalControlConfigModalVisible(false);
                  initBoard();
                }
              });
            }
            }
          />
          <GroupAddModel
            visible={groupAddModalVisible}
            onCancel={() => setGroupAddModalVisible(false)}
            widgets={notInGroupWidgets}
            onSure={(groupName: string, widgets: string[]) => {
              const obj: any = {
                dashboardId: board.id,
                groupName,
              };
              if (widgets.length) {
                obj.widgets = widgets;
              }
              dispatch({
                type: 'board/saveCreateGroup',
                payload: obj,
                callback: (res: IResponse) => {
                  const { header } = res;
                  if (header.code === 200) {
                    message.success('创建分组成功');
                    setGroupAddModalVisible(false);
                    initBoard();
                  } else {
                    message.warning('创建分组失败');
                  }
                },
              });
            }
            }
          />
          <ViewSelect
            views={sheetList}
            visible={viewSelectVisible}
            onCanel={() => setViewSelectVisible(false)}
            onSave={(viewId: number) => {
              addWidget(viewId);
            }}
          />
          <Modal
            visible={widgetAddModalVisible}
            onCancel={() => setWidgetAddModalVisible(false)}
            onOk={() => {
              const widgets = new Set(expandedKeys.map(v => Number(v.split('-')[1])));
              addWidgets({ dashboardId: board.id, widgets:Array.from(widgets) }).then((res: IResponse) => {
                if (res.header.code === 200) {
                  setWidgetAddModalVisible(false);
                  initBoard();
                }
              });
            }}
          >
            <TreeSelect
              allowClear
              treeCheckable
              showSearch={false}
              treeIcon
              multiple
              showCheckedStrategy={TreeSelect.SHOW_CHILD}
              treeData={widgetTrees}
              onChange={(v: any[]) => {
                setExpandedKeys(v);
              }}
              style={{
                width: '100%',
              }}
              // expandedKeys={expandedKeys}
            />
          </Modal>
          <div className={styles.tabBtn} onClick={() => setViewSelectVisible(true)}>
            <PlusOutlined
              className={styles.leftIcon}
            />
            新增
          </div>
          <div className={styles.tabBtn}
               onClick={() => {
                 setGlobalControlConfigModalVisible(true);
               }}
          >
            <FilterOutlined className={styles.leftIcon} />
            全局筛选
          </div>
          <div className={styles.tabBtn} onClick={() => setGroupAddModalVisible(true)}>
            <GroupOutlined className={styles.leftIcon} />
            创建分组
          </div>
          <div className={styles.tabBtn} onClick={() => setWidgetAddModalVisible(true)}>
            <FundProjectionScreenOutlined className={styles.leftIcon} />
            复用组件
          </div>
          <div className={styles.tabBtn} onClick={() => setGroupAddModalVisible(true)}>
            <FundProjectionScreenOutlined className={styles.leftIcon} />
            角色权限
          </div>
        </div>
        <div className={styles.content}>
          <div className={styles.designHeader}>
            <FilterForm
              board={board}
              onSave={(value: any) => {
                setFilterValues(value);
              }}
            />
            <div className={styles.groupTabs}>
              {groups.map((g) => {
                const isActive = currentGroupId === g.id;
                const isMenuActive = isActive && g.id !== -1 && menuHover;
                const onMouseOver = () => {
                  if (isActive) {
                    setMenuHover(true);
                  }
                };
                const onMouseLeave = () => {
                  if (isActive) {
                    setMenuHover(false);
                  }
                };
                return (
                  // eslint-disable-next-line jsx-a11y/mouse-events-have-key-events
                  <div
                    key={g.id}
                    className={styles.groupItem}
                    onMouseOver={onMouseOver}
                    onMouseLeave={onMouseLeave}
                  >
                    <div className={classnames({
                      [styles.groupTitle]: true,
                      [styles.groupTitleOn]: isActive,
                    })}
                         onClick={() => {
                           setMenuHover(true);
                           setCurrentGroupId(g.id);
                           setCurrentGroupWidgetIds(g.widgets.split(',').map(d => Number(d)));
                         }}
                    >
                      {g.groupName}
                    </div>
                    <div
                      style={{ width: '3px', marginLeft: '8px' }}
                    >
                      {isMenuActive ?
                        <Dropdown overlay={tabMenu} trigger={['click']}>
                          <i className='fa fa-ellipsis-v' aria-hidden='true' style={{ color: '#1890FF' }} />
                        </Dropdown>

                        : ''}
                    </div>


                  </div>);
              })}
            </div>
          </div>
          <div className={styles.pcDesignContain}>
            <PCWidgetLayout
              filterControl={getDashboardWidgetFilters(filterValues, controls)}
              widgets={board.widgets}
              groupWidgetIds={currentGroupWidgetIds}
              removeWidgets={currentGroupId === -1 ? removeWidgets : groupRemoveWidget}
            />
          </div>
        </div>
      </div>
    </div>
  );
};

export default connect(({ sheet, panel, user }: ConnectState) => ({
  sheetList: sheet.sheetList,
  dashboard: panel.dashboard,
  currentUser: user.currentUser ? user.currentUser : {},
}))(BoardDesign);
